package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.constant.SecurityConstants;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.converter.UserConverter;
import com.settlement.system.common.util.SecurityUtils;
import com.settlement.system.mapper.SysUserMapper;
import com.settlement.system.model.dto.UserAuthInfo;
import com.settlement.system.model.bo.UserBO;
import com.settlement.system.model.bo.UserFormBO;
import com.settlement.system.model.entity.SysStore;
import com.settlement.system.model.entity.SysUser;
import com.settlement.system.model.entity.SysUserRole;
import com.settlement.system.model.form.UserForm;
import com.settlement.system.model.query.UserPageQuery;
import com.settlement.system.model.vo.UserExportVO;
import com.settlement.system.model.vo.UserInfoVO;
import com.settlement.system.model.vo.UserPageVO;
import com.settlement.system.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户业务实现类
 *
 * @author haoxr
 * @since 2022/1/14
 */
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    private final PasswordEncoder passwordEncoder;

    private final SysUserRoleService userRoleService;

    private final UserConverter userConverter;

    private final SysMenuService menuService;

    private final SysRoleService roleService;

    private final RedisTemplate redisTemplate;

    private final SysDictService dictService;

    private final SysStoreService storeService;

    private final String STORE = "store";

    /**
     * 获取用户分页列表
     *
     * @param queryParams
     * @return
     */
    @Override
    public IPage<UserPageVO> getUserPage(UserPageQuery queryParams) {

        // 参数构建
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<UserBO> page = new Page<>(pageNum, pageSize);

        // 查询数据
        Page<UserBO> userBoPage = this.baseMapper.getUserPage(page, queryParams);

        // 实体转换
        Page<UserPageVO> userVoPage = userConverter.bo2Vo(userBoPage);

        // 转换店铺名称
        List<SysStore> options = storeService.list();
        List<UserPageVO> voList = userVoPage.getRecords();
        for (UserPageVO vo : voList) {
            String storeIds = vo.getStoreIds();
            if (StringUtils.hasText(storeIds)) {
                String[] keyArray = storeIds.split(",");
                List<String> keyNames = new ArrayList<>();
                for (String key : keyArray) {
                    keyNames.add(options.stream().filter(option -> option.getId().toString().equals(key)).findFirst().map(SysStore::getCommercePlatformStoreName).orElse(null));
                }
                vo.setStoreNames(String.join(",", keyNames));
            }
        }
        return userVoPage;
    }

    /**
     * 获取用户详情
     *
     * @param userId
     * @return
     */
    @Override
    public UserForm getUserFormData(Long userId) {
        UserFormBO userFormBO = this.baseMapper.getUserDetail(userId);
        // 实体转换po->form
        UserForm userForm = userConverter.bo2Form(userFormBO);
        return userForm;
    }

    /**
     * 新增用户
     *
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    public boolean saveUser(UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
        Assert.isTrue(count == 0, "登录手机号已存在");

        // 判断是否存在角色负责人
        if (userForm.getManager() != null && userForm.getManager() == 1 && userForm.getRoleIds() != null && userForm.getRoleIds().size() > 0) {
            // 判断是否角色下存在负责人
            for (Long roleId : userForm.getRoleIds()) {
                // 找到这个角色下的所有人，判断是否存在是负责人的用户
                List<SysUserRole> sysUserRoles = userRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
                if (sysUserRoles.size() > 0) {
                    List<SysUser> sysUsers = this.list(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, sysUserRoles.stream().map(SysUserRole::getUserId).toList()));
                    if (sysUsers.size() > 0) {
                        for (SysUser sysUser : sysUsers) {
                            // 如果存在是负责人，并且不是当前人的需要提醒
                            Assert.isFalse(!sysUser.getId().equals(userForm.getId()) && sysUser.getManager() != null && sysUser.getManager() == 1, "当前所选的角色已经存在角色负责人，不能重复设置");
                        }
                    }
                }
            }
        }

        // 实体转换 form->entity
        SysUser entity = userConverter.form2Entity(userForm);

        // 设置默认加密密码
        String defaultEncryptPwd = passwordEncoder.encode(userForm.getPassword());
        entity.setPassword(defaultEncryptPwd);

        // 新增用户
        boolean result = this.save(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 更新用户
     *
     * @param userId   用户ID
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    @Transactional
    public boolean updateUser(Long userId, UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username).ne(SysUser::getId, userId));
        Assert.isTrue(count == 0, "用户名已存在");

        // 判断是否存在角色负责人
        if (userForm.getManager() != null && userForm.getManager() == 1 && userForm.getRoleIds() != null && userForm.getRoleIds().size() > 0) {
            // 判断是否角色下存在负责人
            for (Long roleId : userForm.getRoleIds()) {
                // 找到这个角色下的所有人，判断是否存在是负责人的用户
                List<SysUserRole> sysUserRoles = userRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
                if (sysUserRoles.size() > 0) {
                    List<SysUser> sysUsers = this.list(new LambdaQueryWrapper<SysUser>().in(SysUser::getId, sysUserRoles.stream().map(SysUserRole::getUserId).toList()));
                    if (sysUsers.size() > 0) {
                        for (SysUser sysUser : sysUsers) {
                            // 如果存在是负责人，并且不是当前人的需要提醒
                            Assert.isFalse(!sysUser.getId().equals(userForm.getId()) && sysUser.getManager() != null && sysUser.getManager() == 1, "当前所选的角色已经存在角色负责人，不能重复设置");
                        }
                    }
                }
            }
        }

        // form -> entity
        SysUser entity = new SysUser();
        BeanUtil.copyProperties(userForm, entity);

        // 修改用户
        boolean result = this.updateById(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 删除用户
     *
     * @param idsStr 用户ID，多个以英文逗号(,)分割
     * @return
     */
    @Override
    public boolean deleteUsers(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.stream(idsStr.split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<SysUser> users = this.listByIds(ids);
        Assert.isTrue(users.stream().noneMatch(item -> Objects.equals(SystemConstants.ADMIN_ROLE_CODE.toLowerCase(), item.getUsername())), "删除失败");
        // 删除角色用户中间表数据
        userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
        boolean result = this.removeByIds(ids);
        return result;

    }

    /**
     * 修改用户密码
     *
     * @param userId   用户ID
     * @param password 用户密码
     * @return true|false
     */
    @Override
    public boolean updatePassword(Long userId, String password) {
        return this.update(new LambdaUpdateWrapper<SysUser>().eq(SysUser::getId, userId).set(SysUser::getPassword, passwordEncoder.encode(password)));
    }

    /**
     * 修改用户密码
     *
     * @param oldPassword 用户旧密码
     * @param newPassword 用户新密码
     * @return true|false
     */
    @Override
    public boolean updatePassword(String oldPassword, String newPassword) {
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getId, SecurityUtils.getUser().getUserId()));
        if (passwordEncoder.matches(oldPassword, user.getPassword())) {
            user.setPassword(passwordEncoder.encode(newPassword));
            this.updateById(user);
            return true;
        }
        return false;
    }

    /**
     * 根据用户名获取认证信息
     *
     * @param username 用户名
     * @return 用户认证信息 {@link UserAuthInfo}
     */
    @Override
    public UserAuthInfo getUserAuthInfo(String username) {
        UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
        if (userAuthInfo != null) {
            Set<String> roles = userAuthInfo.getRoles();
            if (CollectionUtil.isNotEmpty(roles)) {
                Set<String> perms = menuService.listRolePerms(roles);
                userAuthInfo.setPerms(perms);
            }

            // 获取最大范围的数据权限
            Integer dataScope = roleService.getMaximumDataScope(roles);
            userAuthInfo.setDataScope(dataScope);
        }
        return userAuthInfo;
    }


    /**
     * 获取导出用户列表
     *
     * @param queryParams
     * @return
     */
    @Override
    public List<UserExportVO> listExportUsers(UserPageQuery queryParams) {
        List<UserExportVO> list = this.baseMapper.listExportUsers(queryParams);
        return list;
    }

    /**
     * 获取登录用户信息
     *
     * @return
     */
    @Override
    public UserInfoVO getUserLoginInfo() {
        // 登录用户entity
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, SecurityUtils.getUser().getUsername()).select(SysUser::getId, SysUser::getNickname, SysUser::getAvatar, SysUser::getManager));
        // entity->VO
        UserInfoVO userInfoVO = userConverter.entity2UserInfoVo(user);

        // 用户角色集合
        Set<String> roles = SecurityUtils.getRoles();
        userInfoVO.setRoles(roles);

        // 用户权限集合
        Set<String> perms = (Set<String>) redisTemplate.opsForValue().get(SecurityConstants.USER_PERMS_CACHE_PREFIX + user.getId());
        userInfoVO.setPerms(perms);
        userInfoVO.setManager(user.getManager());
        userInfoVO.setIsRoot(SecurityUtils.isRoot());
        return userInfoVO;
    }

    @Override
    public List<SysUser> getByDeptId(Long deptId) {
        return this.list(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId, deptId));
    }
}
